package com.jcroke.hercules.examples;
// Description taken from http://docs.codehaus.org/display/JANINO/Home
//What is Janino?

// Janino is a super-small, super-fast Java™ compiler. Not only can it compile a set of 
// source files to a set of class files like the JAVAC tool, but also can it compile a Java™ 
// expression, block, class body or source file in memory, load the bytecode and execute it 
// directly in the same JVM. Janino is not intended to be a development tool, but an embedded 
// compiler for run-time compilation purposes, e.g. expression evaluators or "server pages" 
// engines like JSP.

// This demos a simple use-case in the context of creating a transformer in PC3
// and uses data that would be gathered using SPARQL and a necessary supporting
// ontology.

import java.io.Reader;
import java.io.StringReader;

import org.codehaus.commons.compiler.*;

public final class Demo {

	private Demo() {
	}

	public static void main(String[] args) throws Exception {

		IScriptEvaluator se = CompilerFactoryFactory
				.getDefaultCompilerFactory().newScriptEvaluator();

		// ///////////////////////////////////////////////////////////
		// read params (SPARQL query)
		// ///////////////////////////////////////////////////////////

		// select datum has operator
		// imports, return_type, thrown_exceptions,
		// arguments, parameter_names, parameter_types, return_type

		// return imports returns:
		// com.jcroke.hercules.examples.*
		String[] returnedImports = new String[] { "com.jcroke.hercules.examples.*" };
		se.setDefaultImports(returnedImports);

		// return type query returns:
		// com.jcroke.hercules.examples.Datum
		String returnedType = "com.jcroke.hercules.examples.Datum";
		se.setReturnType(Class.forName(returnedType));

		// exceptions types returns:
		// com.jcroke.hercules.examples.DatumException
		String[] returnedExceptions = new String[] { "com.jcroke.hercules.examples.DatumException", };
		Class<?>[] retExceptionClasses = new Class<?>[returnedExceptions.length];
		for (int i = 0; i < returnedExceptions.length; i++) {
			retExceptionClasses[i] = Class.forName(returnedExceptions[i]);
		}
		se.setThrownExceptions(retExceptionClasses);

		// parameter_datum_addresses query returns:
		// navtr_input_home_mcc
		// navtr_input_home_mnc
		// navtr_input_remote_mcc
		// navtr_input_remote_mnc
		String[] retParamDatumAddresses = new String[] {
				"navtr_input_home_mcc", "navtr_input_home_mnc",
				"navtr_input_roaming_mcc", "navtr_input_roaming_mnc" };

		// parameter_names query returns:
		String[] retParamNames = new String[] { "a", "b", "c", "d" };

		// parameter_type query returns:
		// com.jcroke.hercules.examples.dString
		// com.jcroke.hercules.examples.dString
		// com.jcroke.hercules.examples.dString
		// com.jcroke.hercules.examples.dString
		String[] retParamTypes = new String[] {
				"com.jcroke.hercules.examples.dString",
				"com.jcroke.hercules.examples.dString",
				"com.jcroke.hercules.examples.dString",
				"com.jcroke.hercules.examples.dString" };

		// query logic returns:
		// Function to concatenate mcc/mnc for home and roaming based on
		// existence
		// of fields.
		String code = "dString r = new dString();"
				+ "dBoolean b0 = new dBoolean(false);"
				+ "dBoolean b1 = new dBoolean(false);"
				+ "if (!a.isEmpty() && !a.isNull() && !b.isEmpty() && !b.isNull()) {"
				+ "r.concat(a.toString() + \",\" + b.toString());"
				+ "b0.setValue(true);"
				+ "}"
				+ "if (!c.isEmpty() && !c.isNull() && !d.isEmpty() && !d.isNull()) {"
				+ "r.concat((b0.getValue() == true ? \":\" : \"\") + c.toString() + \",\" + d.toString());"
				+ "b1.setValue(true);"
				+ "}"
				+ "r.concat((b0.or(b1) ? \":\" : \"\") + b0.and(b1));" 
				+ "return r;";

		// ///////////////////////////////////////////////////////////////////////
		// Using mock Mem, lookup Datum objects in memory by address field.
		// Pass array of Datum refs and arguments to function.
		// ///////////////////////////////////////////////////////////////////////
		nMem mem = new nMem();

		if (retParamTypes.length != retParamNames.length) {
			System.out.println("error: ");
		}

		Class<?>[] operatorParamTypes = new Class<?>[retParamTypes.length];
		String[] operatorParamNames = new String[retParamTypes.length];
		Datum[] operatorArgs = new Datum[retParamTypes.length];

		for (int i = 0; i < retParamTypes.length; i++) {
			operatorParamNames[i] = retParamNames[i];
			operatorParamTypes[i] = Class.forName(retParamTypes[i]);
			operatorArgs[i] = mem.getDatumByAddress(retParamDatumAddresses[i]);
		}
		se.setParameters(operatorParamNames, operatorParamTypes);

		// ///////////////////////////////////////////////////////////////////////
		// in-mem compile
		// ///////////////////////////////////////////////////////////////////////
		Reader script = new StringReader(code);
		se.cook(script);

		// ///////////////////////////////////////////////////////////////////////
		// run in jvm
		// ///////////////////////////////////////////////////////////////////////
		dString R = (dString) se.evaluate(operatorArgs);
		System.out.println("r: " + R.toString());
	}
}